#pragma once

#include <iostream>
using namespace std;
#include <strings.h>
#include <string.h>
#include <unistd.h>
#include <functional>
#include <pthread.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <memory>
#include "InetAddr.hpp"
#include "Socket.hpp"
#include "Http.hpp"

using namespace Socket_ns;

using http_server_t = function<std::string(std::string &)>;

enum
{
    SOCK_ERROR = 1,
    BIND_ERROR,
    USAGE_ERROR,
    RECV_ERROR
};

const static int defaultsockfd = -1;
const static int gbacklog = 8;

class TcpServer; // 先声明，再使用 !!!

class ServerData
{
public:
    ServerData(TcpServer *tsvr_ptr, socket_sptr socket, InetAddr addr)
        : _tsvr_ptr(tsvr_ptr), _peer(socket), _addr(addr)
    {
    }

    ~ServerData()
    {
    }

public:
    TcpServer *_tsvr_ptr;
    socket_sptr _peer;
    InetAddr _addr;
};

class TcpServer
{
public:
    TcpServer(uint16_t port, http_server_t server)
        : _isrunning(false)
        //, _local_addr(INADDR_ANY, port)//这样是因为这个INADDR_ANY类型不是const char*匹配不到string的构造函数
        , _local_addr("0.0.0.0", port)
        , _listensock(std::make_unique<TcpSocket>())
        , _http_server(server)
    {
        _listensock->BuildListenSock(_local_addr);
    }

    static void *HandlerServer(void *arg)
    {
        pthread_detach(pthread_self()); // 线程分离后，不需要 pthread_join
        ServerData *ptr = static_cast<ServerData *>(arg);

        std::string request, response;
        // 1. 接收应答
        ssize_t n = ptr->_peer->Recv(&request);
        if (n > 0)
        {
            // 2. 发送应答
            response = ptr->_tsvr_ptr->_http_server(request); // 将应答序列化
            ptr->_peer->Send(response);
        }

        // pthread_join(pthread_self(), nullptr);
        return nullptr;
    }

    void Loop()
    {
        _isrunning = true;
        while (_isrunning)
        {
            // 1. accept
            InetAddr peer_addr;
            socket_sptr peer = _listensock->Accept(&peer_addr);
            if (peer == nullptr) continue;
            // std::cout << "获取到一个新的链接" << std::endl;
            // Version 2 多线程版本
            ServerData *data = new ServerData(this, peer, peer_addr);

            pthread_t thread;
            int n = pthread_create(&thread, nullptr, HandlerServer, data);
            if (n < 0)
            {
                cout << __LINE__ << " : server error" << endl;
            }
            // pthread_join(thread, nullptr);
        }
        _isrunning = false;
    }

    ~TcpServer()
    {
    }

private:
    std::unique_ptr<TcpSocket> _listensock;
    InetAddr _local_addr;
    http_server_t _http_server;

    bool _isrunning;
};